package cn.lixin.hrm.config;

import cn.lixin.hrm.MyUserDetailsService;
import cn.lixin.hrm.filter.SmsCheakCodeFilter;
import cn.lixin.hrm.handler.MyAuthenticationFailHandler;
import cn.lixin.hrm.handler.MyAuthenticationSuccessHandler;
import cn.lixin.hrm.handler.MyAuthorFailHandler;
import cn.lixin.hrm.mapper.PermissionMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;

@Component
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {


    /**
     * 加密
     * @return
     */
    @Bean
    public PasswordEncoder getEncoder(){
//        return NoOpPasswordEncoder.getInstance(); 没有编码
        return new BCryptPasswordEncoder();
    }

    /**
     * 用户创建 --写死
     *  从数据库查 需要继承 UserDetailsService
     * @return

    @Bean
    protected UserDetailsService userDetailsService(){
        // 自己创建一个对象
        ArrayList<GrantedAuthority> list = new ArrayList<>();
        User user = new User("lixin","123",list);
        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager(user);
        return manager;
    }
     */



    @Autowired
    private PermissionMapper permissionMapper;

    @Autowired
    private DataSource dataSource;

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Autowired
    private SmsAuthConfig smsAuthConfig;
    /**
     * 持久化到内存
     * @return
     */
    @Bean
    public PersistentTokenRepository getRepository(){
        JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl(); // 这里将token存入数据库不是内存
        jdbcTokenRepository.setDataSource(dataSource);
//        jdbcTokenRepository.setCreateTableOnStartup(true); // 程序启动的时候创建表 只用过一次
        return jdbcTokenRepository;
    }

    /**
     * 方式二 注解
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception{
                http.authorizeRequests()// 授权请求
                .antMatchers(HttpMethod.POST,"/login","/sms/send/**","/smslogin").permitAll() // 放行
                .antMatchers("/login.html").permitAll() // login.html放行
                .anyRequest().authenticated() // 其他需要认证
                .and().formLogin() // 提交表单放行
                .loginPage("/login.html") // 用自己的登录界面
                .loginProcessingUrl("/login") // 表单提交到/login
//                .successForwardUrl("/loginSuccess")   // 设置登錄成功页
                .successHandler(new MyAuthenticationSuccessHandler()) // 调用自己写的成功
                .failureHandler(new MyAuthenticationFailHandler())
                 .and().exceptionHandling().accessDeniedHandler(new MyAuthorFailHandler())
                .and().logout().permitAll()// 放行
                .and().csrf().disable();// 跨站
        /*
            这里配置记住我
         */
        http.rememberMe().userDetailsService((userDetailsService)) // 存什么数据
                .tokenValiditySeconds(3000) // 存多久
                .tokenRepository(getRepository()); // 存到哪

        // 让自己的配置生效
        SmsCheakCodeFilter smsCheakCodeFilter = new SmsCheakCodeFilter();
        // 在UsernamePasswordAuthenticationFilter前生效
        http.addFilterBefore(smsCheakCodeFilter, UsernamePasswordAuthenticationFilter.class);
        // 应用
        http.apply(smsAuthConfig);



    }
    /*@Override 方法一 web方式
    protected void configure(HttpSecurity http) throws Exception{

        ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.authorizeRequests();// 授权请求
        // 查询所有的权限
        List<Permission> permissions = permissionMapper.loadAllPermissions();
        // 访问哪些路径需要哪些权限
        permissions.stream().forEach(permission->{
            registry.antMatchers(permission.getResource()).hasAuthority(permission.getSn());
        });
        registry.antMatchers("/login").permitAll() // 放行
                .anyRequest().authenticated() // 其他需要认证
                .and().formLogin() // 提交表单放行
//                .successForwardUrl("/loginSuccess")   // 设置登錄成功页
                .successHandler(new MyAuthenticationSuccessHandler()) // 调用自己写的成功类
                .failureHandler(new MyAuthenticationFailHandler())
                .and().logout().permitAll()// 放行
                .and().csrf().disable();// 跨站


    }*/
}
